package org.lora.webframework.monitor;

import java.lang.management.ClassLoadingMXBean;
import java.lang.management.CompilationMXBean;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.lora.core.annotation.Action;
import org.lora.core.context.WebContext;
import org.lora.mvc.annotation.RequestPath;
import org.lora.mvc.annotation.ResponseJSON;
import org.lora.mvc.entity.ViewData;
import org.lora.util.DateUtil;
import org.lora.webframework.WebConstant;
import org.lora.webframework.common.WebframeBaseAction;
import org.lora.webframework.util.MathUtil;
import org.lora.webframework.util.PropertiesUtil;

/**
 * <p>
 * Title:SystemMonitorAction
 * </p>
 * <p>
 * Desription:系统监控Action
 * </p>
 * Create Time:2016年7月4日 下午9:31:27
 * 
 * @author Bladnir@outlook.com
 *         <p>
 *         History:
 *         </p>
 *         2016年7月4日 Bladnir Create</br>
 */
@Action
@RequestPath(path = "/webframework/monitor/systemMonitor")
public class SystemMonitorAction extends WebframeBaseAction {

	/**
	 * 打开系统信息页面
	 * 
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestPath(path = "/baseInfo")
	public ViewData showBaseInfo() {
		return new ViewData("/jsp/webframework/monitor/baseInfo.jsp");
	}

	/**
	 * 打开线程列表页面
	 * 
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestPath(path = "/threadPool")
	public ViewData showThreadPool() {
		return new ViewData("/jsp/webframework/monitor/threadPool.jsp");
	}

	/**
	 * 打开配置信息浏览页面
	 * 
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestPath(path = "/configView")
	public ViewData showConfigView() {
		return new ViewData("/jsp/webframework/monitor/configView.jsp");
	}

	/**
	 * 配置文件信息浏览页面
	 * 
	 * @return
	 */
	@RequestPath(path = "/propertiesView")
	public ViewData showPropertiesView() {
		return new ViewData("/jsp/webframework/monitor/propertiesView.jsp");
	}

	/**
	 * 获取配置信息数据
	 * 
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestPath(path = "/getConfigViewData")
	@ResponseJSON
	public Object getConfigViewData() {
		return WebContext.getInstance().getConfigXmlEntity();
	}

	/**
	 * 获取配置文件数据
	 * 
	 * @return
	 */
	@RequestPath(path = "/getPropertiesData")
	@ResponseJSON
	public Object getPropertiesData() {
		return PropertiesUtil.getAllValueMap(PropertiesUtil.DEFAULT_PROPERTIE_FILE_NAME);
	}

	/**
	 * 获取线程列表数据
	 * 
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestPath(path = "/getThreadPoolData")
	@ResponseJSON
	public Object getThreadPoolData() {

		Map<String, Object> resultMap = new HashMap<>();

		try {
			ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
			ThreadInfo[] thiArray = threadMXBean.dumpAllThreads(true, true);

			RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
			long upTime = runtimeMXBean.getUptime();

			List<Map<String, Object>> dataList = new ArrayList<>();
			int count = thiArray.length;
			for (ThreadInfo thi : thiArray) {
				Map<String, Object> dataMap = new HashMap<>();

				List<String> stackTraceElementList = new ArrayList<>();
				for (StackTraceElement ste : thi.getStackTrace()) {
					stackTraceElementList.add(ste.toString());
				}

				long cpuTime = threadMXBean.getThreadCpuTime(thi.getThreadId()) / 1000000;

				dataMap.put("threadId", thi.getThreadId());
				dataMap.put("threadName", thi.getThreadName());
				dataMap.put("threadState", thi.getThreadState().toString());
				dataMap.put("blockedCount", thi.getBlockedCount());
				dataMap.put("blockedTime", thi.getBlockedTime());
				dataMap.put("waitedCount", thi.getWaitedCount());
				dataMap.put("waitedTime", thi.getWaitedTime());
				dataMap.put("stackTraceElementList", stackTraceElementList);
				dataMap.put("lockName", thi.getLockName());
				dataMap.put("lockOwnerId", thi.getLockOwnerId());
				dataMap.put("lockOwnerName", thi.getLockOwnerName());
				dataMap.put("cpuTime", MathUtil.getPercent(Long.toString(cpuTime), Long.toString(upTime), 2));

				dataList.add(dataMap);

			}

			resultMap.put(WebConstant.TABLE_DATA, dataList);
			resultMap.put(WebConstant.TABLE_COUNT, count);
		} catch (Exception e) {
			businessLogger.error(e);
		}

		return resultMap;
	}

	/**
	 * 获取JVM基本信息
	 * 
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestPath(path = "/getOverviewData")
	@ResponseJSON
	public Object getOverviewData() {
		Map<String, Object> resultMap = new HashMap<>();
		try {
			OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();

			resultMap.put("systemArch", operatingSystemMXBean.getArch());
			resultMap.put("AvailableProcessors", operatingSystemMXBean.getAvailableProcessors());
			resultMap.put("systemName", operatingSystemMXBean.getName());
			resultMap.put("systemVersion", operatingSystemMXBean.getVersion());
			resultMap.put("systemLoadAverage", operatingSystemMXBean.getSystemLoadAverage());

			MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();

			MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
			MemoryUsage nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();

			resultMap.put("heapMemoryUsageMax", heapMemoryUsage.getMax() / 1048576);
			resultMap.put("heapMemoryUsageUsed", heapMemoryUsage.getUsed() / 1048576);
			resultMap.put("heapMemoryUsageCommitted", heapMemoryUsage.getCommitted() / 1048576);
			resultMap.put("heapMemoryUsageInit", heapMemoryUsage.getInit() / 1048576);

			resultMap.put("nonHeapMemoryUsageMax", nonHeapMemoryUsage.getMax() / 1048576);
			resultMap.put("nonHeapMemoryUsageUsed", nonHeapMemoryUsage.getUsed() / 1048576);
			resultMap.put("nonHeapMemoryUsageCommitted", nonHeapMemoryUsage.getCommitted() / 1048576);
			resultMap.put("nonHeapMemoryUsageInit", nonHeapMemoryUsage.getInit() / 1048576);

			RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();

			resultMap.put("BootClassPath", runtimeMXBean.getBootClassPath());
			resultMap.put("LibraryPath", runtimeMXBean.getLibraryPath());
			resultMap.put("ManagementSpecVersion", runtimeMXBean.getManagementSpecVersion());
			resultMap.put("RunVmName", runtimeMXBean.getName());
			resultMap.put("SpecName", runtimeMXBean.getSpecName());
			resultMap.put("SpecVendor", runtimeMXBean.getSpecVendor());
			resultMap.put("SpecVersion", runtimeMXBean.getSpecVersion());
			resultMap.put("StartTime", DateUtil.getFormatDateLong(DateUtil.YYYY_MM_DD_HH_MM_SS, runtimeMXBean.getStartTime()));
			resultMap.put("Uptime", runtimeMXBean.getUptime() / 1000);
			resultMap.put("VmName", runtimeMXBean.getVmName());
			resultMap.put("VmVendor", runtimeMXBean.getVmVendor());
			resultMap.put("VmVersion", runtimeMXBean.getVmVersion());
			resultMap.put("argList", runtimeMXBean.getInputArguments());

			ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();
			resultMap.put("LoadedClassCount", classLoadingMXBean.getLoadedClassCount());
			resultMap.put("TotalLoadedClassCount", classLoadingMXBean.getTotalLoadedClassCount());
			resultMap.put("UnloadedClassCount", classLoadingMXBean.getUnloadedClassCount());

			CompilationMXBean compilationMXBean = ManagementFactory.getCompilationMXBean();
			resultMap.put("CompilationName", compilationMXBean.getName());
			resultMap.put("TotalCompilationTime", compilationMXBean.getTotalCompilationTime() / 1000);

			List<GarbageCollectorMXBean> garbageCollectorMXBeanList = ManagementFactory.getGarbageCollectorMXBeans();
			List<Map<String, Object>> gcInfoList = new ArrayList<>();
			for (GarbageCollectorMXBean gcBean : garbageCollectorMXBeanList) {
				Map<String, Object> map = new HashMap<>();

				map.put("Name", gcBean.getName());
				map.put("CollectionCount", Long.toString(gcBean.getCollectionCount()));
				map.put("CollectionTime", Long.toString(gcBean.getCollectionTime() / 1000));
				map.put("poolNameArray", gcBean.getMemoryPoolNames());

				gcInfoList.add(map);
			}
			resultMap.put("gcInfoList", gcInfoList);

			List<Map<String, Object>> memoryList = getMemoryPoolInfo();

			resultMap.put("memoryList", memoryList);

		} catch (Exception e) {
			businessLogger.error(e);

		}

		return resultMap;
	}

	private List<Map<String, Object>> getMemoryPoolInfo() {

		List<Map<String, Object>> resultList = new ArrayList<>();

		List<MemoryPoolMXBean> list = ManagementFactory.getMemoryPoolMXBeans();

		for (MemoryPoolMXBean pool : list) {

			Map<String, Object> dataMap = new HashMap<>();
			MemoryUsage mu = pool.getUsage();

			dataMap.put("poolName", pool.getName());
			dataMap.put("memoryType", pool.getType().toString());

			dataMap.put("Committed", mu.getCommitted() / 1048576);
			dataMap.put("Init", mu.getInit() / 1048576);
			dataMap.put("Max", mu.getMax() / 1048576);
			dataMap.put("Used", mu.getUsed() / 1048576);
			dataMap.put("percent", MathUtil.getPercent(Long.toString(mu.getUsed()), Long.toString(mu.getMax()), 2));
			
			resultList.add(dataMap);

		}

		return resultList;

	}
}
